package infra

import (
	"github.com/sirupsen/logrus"
	"github.com/tietang/props/kvs"
	"reflect"
	"runtime"
	"sync"
)

// 应用程序启动管理
type BootApplication struct {
	conf           kvs.ConfigSource
	starterContext StarterContext
	wait           sync.WaitGroup
}

func NewBootApplication(conf kvs.ConfigSource) *BootApplication {
	b := &BootApplication{
		conf:           conf,
		starterContext: StarterContext{},
	}
	b.starterContext[KeyProps] = conf
	return b
}
func (b *BootApplication) Start() {
	//1.初始化starter
	b.init()
	//2.安装starter
	b.setup()
	//3.启动starter
	b.start()
	//4.等待其余线程结束
	b.wait.Wait()
}

func (b *BootApplication) init() {
	for _, starter := range StarterRegister.AllStarters() {
		starter.Init(b.starterContext)
	}
}
func (b *BootApplication) setup() {
	for _, starter := range StarterRegister.AllStarters() {
		starter.Setup(b.starterContext)
	}
}
func (b *BootApplication) start() {

	for i, starter := range StarterRegister.AllStarters() {
		typ := reflect.TypeOf(starter)
		logrus.Debug("Starting: ", typ.String())
		//如果是最后一个可阻塞的，直接启动并阻塞
		if starter.StartBlocking() {
			if i+1 == len(StarterRegister.AllStarters()) {
				starter.Start(b.starterContext)
			} else {
				//如果是，使用goroutine来异步启动，
				// 防止阻塞后面start
				// 加入waitGroup
				b.wait.Add(1)
				go starter.Start(b.starterContext)
				runtime.Gosched()
			}
		} else {
			starter.Start(b.starterContext)
		}

	}

}
